package com.simple.study.controller;

import com.simple.study.base.controller.BaseController;
import com.simple.study.entity.Result;
import com.simple.study.entity.ShopResult;
import com.simple.study.pojo.AuthToken;
import com.simple.study.pojo.User;
import com.simple.study.service.LoginService;
import com.simple.study.util.CookieUtil;
import com.simple.study.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName LoginController
 * @Author SimpleTree
 **/
@RestController
public class LoginController extends BaseController {

    @Autowired
    private LoginService loginService;
    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 登录请求
     * 用oauth下不能用此方法登录，登录http://localhost:8888/auth/oauth/login
     * @param user
     * @return
     */
    @PostMapping("/loginNoOAuth")
    public Result login(User user, HttpServletResponse response) {
        boolean login = loginService.login(user);
        if (login) {
            Map<String, String> info = new HashMap<>();
            info.put("username", user.getUsername());
            String token = JwtUtil.createJWT(UUID.randomUUID().toString(), user.getUsername(), null);
            info.put("token", token);
            return success(info);
        } else {
            return error();
        }
    }

    @PostMapping("/login")
    public ShopResult loginT(@RequestBody User user, HttpServletResponse response) {
        //1.申请令牌,需要从网关出访问oauth地址
        ServiceInstance serviceInstance = loadBalancerClient.choose("gateway");
        URI uri = serviceInstance.getUri();
        String url = uri  + "/auth/oauth/token";

        MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("grant_type", "password");
        body.add("username", user.getUsername());
        body.add("password", user.getPassword());

        MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
        headers.add("Authorization", this.getHttpBasic("simple", "simple"));
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);

        restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
            @Override
            public void handleError(ClientHttpResponse response) throws IOException {
                if (response.getRawStatusCode() != 400 && response.getRawStatusCode() != 401) {
                    super.handleError(response);
                }
            }
        });

        ResponseEntity<Map> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class);
        Map map = responseEntity.getBody();
        if (map == null || map.get("access_token") == null || map.get("refresh_token") == null || map.get("jti") == null) {
            throw new RuntimeException("申请令牌失败");
        }

        //2.封装结果数据
        AuthToken authToken = new AuthToken();
        authToken.setAccessToken((String) map.get("access_token"));
        authToken.setRefreshToken((String) map.get("refresh_token"));
        authToken.setJti((String) map.get("jti"));

        //3.将jti作为redis的key，jwt作为redis的value保存5个小时
        stringRedisTemplate.boundValueOps(authToken.getJti()).set(authToken.getAccessToken(), 3600*5, TimeUnit.SECONDS);
        //将jti存入cookie
        this.saveJti2Cookie(authToken.getJti(), response);

        //4.返回user信息
        User userInfo = loginService.userInfo(user.getUsername());
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("id", userInfo.getUserId());
        resultMap.put("rid", userInfo.getRoleId());
        resultMap.put("username", userInfo.getUsername());
        resultMap.put("mobile", userInfo.getMobile());
        resultMap.put("email", userInfo.getEmail());
        resultMap.put("token", authToken.getAccessToken());
        return shopSuccess(200,"登录成功",resultMap);
    }

    private String getHttpBasic(String clientId, String clientSecret) {
        String value = clientId + ":" + clientSecret;
        byte[] encode = Base64Utils.encode(value.getBytes());
        return "Basic " + new String(encode);
    }
    private void saveJti2Cookie(String jti, HttpServletResponse response) {
        CookieUtil.addCookie(response,"localhost","/","jti",jti,-1,false);
    }
}
